package model;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;

public class House {

	private ModelClass modelClass;
	private ArrayList<Section> sections;
	private ArrayList<Equipment> equipments;
	private ArrayList<HouseMeas> houseMeasurements;
	private final int id;
	private String name;
	private boolean autoClimateControl;
	private int currentTemp;
	private int currentLight;
	private int currentCO2;
	private int currentHumidity;
	private int optTemp;
	private int optLight;
	private int optCO2;
	private int optHumidity;
	private int tilePicture;
	private boolean alarm;
	private boolean notification;
	private boolean empty;
	private double runningCost;
	private double totalCost;
	private JButton tile;

	public House(ModelClass modelClass, int id, String name) {
		this.modelClass = modelClass;
		this.name = name;
		this.equipments = new ArrayList<Equipment>();
		this.id = id;
		houseMeasurements = new ArrayList<HouseMeas>();
		sections = new ArrayList<Section>();
		tilePicture = 1;
		autoClimateControl = true;
		alarm = false;
		notification = false;
		empty = false;

		currentTemp = 20;
		currentLight = 150;
		currentHumidity = 80;
		currentCO2 = 250;

	}

	// Method that adds sections to arraylist and maybe to the database
	// depending on the value of the boolean dBOrNot
	public void addSections(ArrayList<Section> addedSections, boolean dBOrNot) {
		for (Section section : addedSections) {
			sections.add(section);
		}
		if (dBOrNot) {
			modelClass.getDb().uploadSection(sections);
		}
	}

	// Method that adds equipments to arraylist and maybe to the database
	// depending on the value of the boolean dBOrNot
	public void addEquipment(Equipment equipment, boolean dBOrNot) {
		equipments.add(equipment);
		if (dBOrNot) {
			modelClass.getDb().uploadEquipment(id, equipment.getName());
		}
	}

	// Not fully implemented
	public void calcRunningCost() {
		runningCost = 0;
		for (Equipment eq : equipments) {
			if (eq.isOnOff()) {
				runningCost += eq.getCost();
			}
		}

	}

	// Checks for alarm, empty and finished-notification for house
	public void checkAlarmEmptyNotiFication() {
		alarm = false;
		notification = false;
		empty = false;
		for (Section section : sections) {
			if (section.getAlarm()) {
				alarm = true;
			}
			if (section.isNotification()) {
				notification = section.isNotification();
			}
			if (section.getEmpty()) {
				empty = section.getEmpty();
			}
		}
	}

	// Method that checks if the possible equipments are on or off
	public void turnEuipments(boolean[] turnEquipments) {
		for (Equipment equip : equipments) {
			if (equip.getName().equals("Active Cooling")) {
				equip.setOnOff(turnEquipments[0]);
			} else if (equip.getName().equals("CO2")) {
				equip.setOnOff(turnEquipments[1]);
			} else if (equip.getName().equals("Curtain")) {
				equip.setOnOff(turnEquipments[2]);
			} else if (equip.getName().equals("Light")) {
				equip.setOnOff(turnEquipments[3]);
			} else if (equip.getName().equals("Sprinkler")) {
				equip.setOnOff(turnEquipments[4]);
			} else if (equip.getName().equals("Termostats")) {
				equip.setOnOff(turnEquipments[5]);
			} else if (equip.getName().equals("Windows")) {
				equip.setOnOff(turnEquipments[6]);
			}

		}
	}

	// not fully implemented
	public void addRunningCostToTotalCost(double runCost) {
		totalCost += runCost;
	}

	// Add sections to arraylist
	public void addSection(Section section) {
		sections.add(section);
	}
	// Method that get a section by name
	public Section getSectionByName(String name) {
		for (Section section : sections) {
			if (section.getName().equals(name)) {
				return section;
			}
		}
		return null;
	}

	// Method that sets a new climate and the current equipments react upon it.
	public void setCurrentMeas(Measurement measurement) {
		currentTemp = (int) measurement.getTemp();
		currentLight = (int) measurement.getLight();
		currentHumidity = currentHumidity - 10;
		if (currentCO2 >= 10) {
			currentCO2 = currentCO2 - 10;
		}
		// Reaction of Equipments
		for (Equipment equipment : equipments) {
			if (equipment.isOnOff()) {
				if (equipment.getName().equals("Active Cooling")) {
					currentTemp -= 5;
				} else if (equipment.getName().equals("CO2")) {
					currentCO2 = optCO2;
				} else if (equipment.getName().equals("Curtain")) {
					currentLight = optLight;
				} else if (equipment.getName().equals("Light")) {
					currentLight = optLight;
				} else if (equipment.getName().equals("Sprinkler")) {
					currentHumidity = optHumidity;
				} else if (equipment.getName().equals("Termostats")) {
					currentTemp += 5;
				} else if (equipment.getName().equals("Windows")) {
					currentTemp -= 5;
					currentCO2 = 0;
				}
			}
		}
		HouseMeas houseMeas = new HouseMeas(currentTemp, currentLight,
				currentCO2, currentHumidity);
		houseMeasurements.add(houseMeas);
	}

	// Method that calculates the average optimal growing conditions for the house
	public void setOptimalMeas() {
		optTemp = 0;
		optCO2 = 0;
		optHumidity = 0;
		optLight = 0;
		int amountOfPlants = 0;
		for (Section section : sections) {
			if (section.getPlant() != null) {
				amountOfPlants++;
				optTemp += section.getPlant().getOptTemp();
				optCO2 += section.getPlant().getOptCO2();
				optHumidity += section.getPlant().getOptFugt();
				optLight += section.getPlant().getOptLigt();
			}
		}
		if (amountOfPlants > 0) {
			optTemp = optTemp / amountOfPlants;
			optCO2 = optCO2 / amountOfPlants;
			optHumidity = optHumidity / amountOfPlants;
			optLight = optLight / amountOfPlants;

		}
	}

	// Method that creates tile with specific layout
	public JButton getHouseTile() {
		tile = new JButton();
		tile.setBorder(null);
		tile.setBackground(new Color(34, 177, 76));
		BufferedImage img = modelClass.getVariables().getImgTile();
		BufferedImage imgPressed = modelClass.getVariables()
				.getImgTilePressed();
		HouseThread thread = new HouseThread(tile, modelClass);
		tile.setIcon(new ImageIcon(thread.process(img, 1)));
		tile.setPressedIcon(new ImageIcon(thread.process(imgPressed, 1)));

		return tile;
	}

	// Getters and setters
	public int getId() {
		return id;
	}

	public ArrayList<Section> getSections() {
		return sections;
	}

	public void setSections(ArrayList<Section> sections) {
		this.sections = sections;
	}

	public ArrayList<Equipment> getEquipments() {
		return equipments;
	}

	public void setEquipments(ArrayList<Equipment> equipments) {
		this.equipments = equipments;
	}

	public int getCurrentTemp() {
		return currentTemp;
	}

	public void setCurrentTemp(int currentTemp) {
		this.currentTemp = currentTemp;
	}

	public int getCurrentLight() {
		return currentLight;
	}

	public void setCurrentLight(int currentLight) {
		this.currentLight = currentLight;
	}

	public int getCurrentCO2() {
		return currentCO2;
	}

	public void setCurrentCO2(int currentCO2) {
		this.currentCO2 = currentCO2;
	}

	public int getCurrentHumidity() {
		return currentHumidity;
	}

	public void setCurrentHumidity(int currentHumidity) {
		this.currentHumidity = currentHumidity;
	}

	public int getOptTemp() {
		return optTemp;
	}

	public void setOptTemp(int optTemp) {
		this.optTemp = optTemp;
	}

	public int getOptLight() {
		return optLight;
	}

	public void setOptLight(int optLight) {
		optLight = optLight;
	}

	public int getOptCO2() {
		return optCO2;
	}

	public void setOptCO2(int optCO2) {
		optCO2 = optCO2;
	}

	public int getOptHumidity() {
		return optHumidity;
	}

	public void setOptHumidity(int optHumidity) {
		optHumidity = optHumidity;
	}

	public String getName() {
		return name;
	}

	public boolean isAlarm() {
		return alarm;
	}

	public void setAlarm(boolean alarm) {
		this.alarm = alarm;
	}

	public boolean isNotification() {
		return notification;
	}

	public void setNotification(boolean notification) {
		this.notification = notification;
	}

	public double getRunningCost() {
		return runningCost;
	}

	public void setRunningCost(double runningCost) {
		this.runningCost = runningCost;
	}

	public ArrayList<HouseMeas> getHouseMeasurements() {
		return houseMeasurements;
	}

	public void setHouseMeasurements(ArrayList<HouseMeas> houseMeasurements) {
		this.houseMeasurements = houseMeasurements;
	}

	public double getTotalCost() {
		return totalCost;
	}

	public void setTotalCost(double totalCost) {
		this.totalCost = totalCost;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean isAutoClimateControl() {
		return autoClimateControl;
	}

	public void setAutoClimateControl(boolean autoClimateControl) {
		this.autoClimateControl = autoClimateControl;
	}

	public JButton getTile() {
		return tile;
	}

	public void setTile(JButton tile) {
		this.tile = tile;
	}

	// Class that will is used to change the images of the tile
	// It's uses a thread that runs in interval changing the image
	class HouseThread extends Thread {
		String s = null;
		JButton tile;
		Boolean tileNr = true;
		Random r = new Random();
		ModelClass modelClass;
		Variables variables;
		// the constructure
		public HouseThread(JButton tile, ModelClass modelClass) {
			this.tile = tile;
			this.modelClass = modelClass;
			this.variables = modelClass.getVariables();
			start();
		}
		//thread that runs
		public void run() {
			while (true) {
				try {
					sleep(r.nextInt(15000) + 5000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				BufferedImage img = null;
				img = variables.getImgTile();
				BufferedImage imgPressed = null;
				imgPressed = variables.getImgTilePressed();
				transitionImage(img);
				tile.setPressedIcon(new ImageIcon(process(imgPressed, 1)));
			}
		}
		// finds out what picture to change to
		public void transitionImage(BufferedImage img) {
			BufferedImage imgStart = null;
			BufferedImage imgEnd = null;
			if (tilePicture == 1) {
				imgStart = process(img, 1);
				imgEnd = process(img, 2);
				tilePicture = 2;
			} else if (tilePicture == 2) {
				imgStart = process(img, 2);
				imgEnd = process(img, 3);
				tilePicture = 3;

			} else if (tilePicture == 3) {

				imgStart = process(img, 3);
				imgEnd = process(img, 1);
				tilePicture = 1;
			}
			double endPos = 100;
			// loop that will illustrate the grafik
			// makes the picture smootly come in from the side
			for (double i = 0; i < endPos; i++) {
				// System.out.println("test");
				try {
					sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				tile.setIcon(new ImageIcon(processTransistionImage(imgStart,
						imgEnd, i, endPos)));
			}
		}
		// that takes to images and merges them together
		public BufferedImage processTransistionImage(BufferedImage imgStart,
				BufferedImage imgEnd, double pos, double endPos) {
			int w = imgStart.getWidth();
			int h = imgStart.getHeight();
			BufferedImage img = new BufferedImage(w, h,
					BufferedImage.TYPE_INT_ARGB);
			Graphics2D g2d = img.createGraphics();
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			double xpos = w / endPos;
			g2d.drawImage(imgStart, (int) (0 + xpos * pos), 0, null);
			g2d.drawImage(imgEnd, -w + (int) (0 + xpos * pos), 0, null);
			return img;
		}
		// method that takes an image and writes the corresponding data onto that image
		public BufferedImage process(BufferedImage old, int type) {
			int w = old.getWidth();
			int h = old.getHeight();
			BufferedImage img = new BufferedImage(w, h,
					BufferedImage.TYPE_INT_ARGB);
			Graphics2D g2d = img.createGraphics();
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			g2d.drawImage(old, 0, 0, null);
			int y = 0;
			if (notification) {
				g2d.drawImage(variables.getImgNotification(), 165, 100, null);
				y += 35;
			}
			if (alarm) {
				g2d.drawImage(variables.getImgWarning(), 165, 100 - y, null);
				y += 35;
			}
			if (empty) {
				g2d.drawImage(variables.getImgEmptyIcon(), 165, 100 - y, null);
			}
			g2d.setPaint(Color.WHITE);
			Font font = variables.getFontTileHeader();
			font = font.deriveFont(30f);
			g2d.setFont(font);
			String s = name;
			g2d.drawString(s, 5, 25);

			if (type == 1) {
				s = "" + sections.size();
				font = font.deriveFont(15f);
				g2d.setFont(font);
				g2d.drawString("Sections: " + s, 5, 45);

				if (autoClimateControl) {
					s = "On";
				} else {
					s = "Off";
				}
				g2d.drawString("Auto Climate: " + s, 5, 60);
				// Not to be run here!!!!!!!!!!!!!!!!!!!
				// calcRunningCost();
				g2d.drawString("Run Cost: " + runningCost, 5, 75);
				// Not to be run here!!!!!!!!!!!!!!!!!!!
				// addRunningCostToTotalCost(runningCost);
				g2d.drawString("Tot Cost: " + totalCost, 5, 90);

			} else if (type == 2) {
				font = font.deriveFont(15f);
				g2d.setFont(font);
				int yIndex = 0;
				String onOff = "";
				for (Equipment eq : equipments) {
					g2d.drawString(eq.getName(), 5, 40 + yIndex * 15);
					if (eq.isOnOff()) {
						onOff = "On";
						g2d.drawString(onOff, 125, 40 + yIndex * 15);
					} else {
						onOff = "Off";
						g2d.drawString(onOff, 125, 40 + yIndex * 15);
					}

					yIndex++;
				}
			} else if (type == 3) {
				font = font.deriveFont(15f);
				g2d.setFont(font);

				FontMetrics metrics = g2d.getFontMetrics(g2d.getFont());
				int curTempSize = metrics.stringWidth("" + currentTemp);
				int optTempSize = metrics.stringWidth("" + optTemp);
				int curHumdSize = metrics.stringWidth("" + currentHumidity);
				int optHumdSize = metrics.stringWidth("" + optHumidity);

				int curLightSize = metrics.stringWidth("" + currentLight);
				int optLightSize = metrics.stringWidth("" + optLight);
				int curCO2Size = metrics.stringWidth("" + currentCO2);
				int optCO2Size = metrics.stringWidth("" + optCO2);

				g2d.drawString("Cur", 70, 50);
				g2d.drawString("Opt", 120, 50);
				g2d.drawString("Temp", 5, 70);
				g2d.drawString("" + currentTemp, 90 - curTempSize, 70);
				g2d.drawString("" + optTemp, 140 - optTempSize, 70);
				g2d.drawString("Humd", 5, 90);
				g2d.drawString("" + currentHumidity, 90 - curHumdSize, 90);
				g2d.drawString("" + optHumidity, 140 - optHumdSize, 90);

				g2d.drawString("Light", 5, 110);
				g2d.drawString("" + currentLight, 90 - curLightSize, 110);
				g2d.drawString("" + optLight, 140 - optLightSize, 110);

				g2d.drawString("CO2", 5, 130);
				g2d.drawString("" + currentCO2, 90 - curCO2Size, 130);
				g2d.drawString("" + optCO2, 140 - optCO2Size, 130);
			}

			g2d.dispose();
			return img;
		}
	}

}
